package com.search.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

public class CodeUtil {

	public static void main(String[] args) throws IOException {
		Map<?, ?> map = new CodeUtil().code(2, 8);
		// 输出图象到本地
		OutputStream out = new FileOutputStream("D:/test/" + System.currentTimeMillis() + ".jpg");
//			ImageIO.write(image, "JPEG", response.getOutputStream());
		ImageIO.write((RenderedImage) map.get("codePic"), "jpeg", out);
		System.out.println("验证码的值为：" + map.get("code"));

	}

	/**
	 * 
	 * @param response
	 * @throws IOException
	 */
	public void getCode(Map<?, ?> map, HttpServletResponse response) throws IOException {

		// 1. 通知浏览器不要缓存
		response.setHeader("Expires", "-1");
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "-1");

		// 2. 输出图象到本地
//		ApplicationHome home = new ApplicationHome(getClass());
//		System.out.println(home.getSource());//E:\JAVA\yj\target\classes
//		System.out.println(System.getProperty("user.dir"));//		E:\JAVA\yj
//		String rootPath = ClassUtils.getDefaultClassLoader().getResource("").getPath() + "static/code/";
		String rootPath=System.getProperty("user.dir")+"/file/code/";
		File path = new File(rootPath);
		if (!path.exists()) {
			path.mkdirs();
		}
		OutputStream out = new FileOutputStream(rootPath + System.currentTimeMillis() + ".jpg");
		ImageIO.write((RenderedImage) map.get("codePic"), "jpeg", out);
		out.flush();
		out.close();

		// 3. 输出到web页面
		ImageIO.write((RenderedImage) map.get("codePic"), "JPEG", response.getOutputStream());
	}

	/**
	 * 校验验证码
	 * 
	 * @param codeSession
	 * @param code
	 * @return
	 * @throws IOException
	 */
	public boolean checkCode(JSONObject rs, String codeSession, String code) {
		if (StringUtil.isEmpty(codeSession)) {
			rs.put("msg", "没有生成验证码信息！");
			return false;
		}
		if (StringUtil.isEmpty(code)) {
			rs.put("msg", "未填写验证码信息！");
			return false;
		}
		if (!codeSession.equalsIgnoreCase(code)) {
			rs.put("msg", "验证码填写错误！");
			return false;
		}
		return true;
	}

	// 图形宽度、高度
	private static final int width = 200;
	private static final int height = 40;
	// 干扰线的长度、频率
	private static final int lineWidth = 2;
	private static final int count = 500;
	// 验证码字体
	private static final String[] fontNames = { "宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312" };
	// 背景色
	private static final Color bgColor = new Color(255, 255, 255);
	// 边框色
	private static final Color bkColor = new Color(0, 0, 0);
	// 随机对象
	private Random random = new Random();

	/**
	 * 验证码
	 * 
	 * @param type 类型（1：数字、2：小写字母、3：大写字母、4：字母、5：混合）
	 * @param len  长度
	 * @throws IOException
	 */
	public Map<String, Object> code(int type, int len) {

		// 在内存中创建图象
		final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 获取图形上下文
		final Graphics2D graphics = (Graphics2D) image.getGraphics();
		// 设定背景颜色
		graphics.setColor(bgColor);
		graphics.fillRect(0, 0, width, height);
		// 设定边框颜色
		graphics.setColor(bkColor);
		graphics.drawRect(0, 0, width - 1, height - 1);

		// 随机产生干扰线，使图象中的认证码不易被其它程序探测到
		for (int i = 0; i < count; i++) {
			graphics.setColor(getRandColor(150, 200));
			final int x = random.nextInt(width - lineWidth - 1) + 1; // 保证画在边框之内
			final int y = random.nextInt(height - lineWidth - 1) + 1;
			final int xl = random.nextInt(lineWidth);
			final int yl = random.nextInt(lineWidth);
			graphics.drawLine(x, y, x + xl, y + yl);
		}

		// 取随机产生的认证码(4位数字)
		final String resultCode = exctractRandCode(type, len);
		for (int i = 0; i < resultCode.length(); i++) {
			// 设置字体颜色
			graphics.setColor(getRandColor(0, 1));
			// 设置字体样式
			graphics.setFont(randomFont());
			// 设置字符，字符间距，上边距
			graphics.drawString(String.valueOf(resultCode.charAt(i)),
					(width / (resultCode.length() * 2 + 1) * (2 * i)) + width / (resultCode.length() * 2 + 1),
					5 * height / 7);
		}

		// 图象生效
		graphics.dispose();

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("code", resultCode);// 存放验证码
		map.put("codePic", image);// 存放生成的验证码BufferedImage对象

		return map;
	}

	// 生成随机的字体
	private Font randomFont() {
		int index = random.nextInt(fontNames.length);
		String fontName = fontNames[index];// 生成随机的字体名称
		int style = random.nextInt(4);// 生成随机的样式, 0(无样式), 1(粗体), 2(斜体), 3(粗体+斜体)
		int size = random.nextInt(5) + 24; // 生成随机字号, 24 ~ 28
		return new Font(fontName, style, size);
	}

	// 生成给定范围随机颜色
	private Color getRandColor(int min, int max) {
		if (min > 255)
			min = 255;
		if (max > 255)
			max = 255;
		final int r = min + random.nextInt(max - min);
		final int g = min + random.nextInt(max - min);
		final int b = min + random.nextInt(max - min);
		return new Color(r, g, b);
	}

	/**
	 * 随机验证码
	 * 
	 * @param field 类型（1：数字、2：小写字母、3：大写字母、4：字母、5：混合）
	 * @param len  长度
	 * @throws IOException
	 */
	private String exctractRandCode(int randCodeType, int randCodeLength) {
		if (randCodeType > 5 || randCodeType < 0) {
			return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
		} else {
			switch (randCodeType) {
			case 1:
				return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
			case 2:
				return RandCodeImageEnum.LOWER_CHAR.generateStr(randCodeLength);
			case 3:
				return RandCodeImageEnum.UPPER_CHAR.generateStr(randCodeLength);
			case 4:
				return RandCodeImageEnum.LETTER_CHAR.generateStr(randCodeLength);
			case 5:
				return RandCodeImageEnum.ALL_CHAR.generateStr(randCodeLength);
			default:
				return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
			}
		}
	}
}

/**
 * 验证码辅助枚举类
 * 
 * 
 */
enum RandCodeImageEnum {
	// 混合字符串
	ALL_CHAR("123456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"),
	// 字符
	LETTER_CHAR("abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"),
	// 小写字母
	LOWER_CHAR("abcdefghjkmnpqrstuvwxyz"),
	// 数字
	NUMBER_CHAR("123456789"),
	// 大写字符
	UPPER_CHAR("ABCDEFGHJKMNPQRSTUVWXYZ");
	// 待生成的字符串
	String charStr;

	private RandCodeImageEnum(final String charStr) {
		this.charStr = charStr;
	}

	/**
	 * 生产随机验证码
	 * 
	 * @param codeLength 验证码的长度
	 * @return 验证码
	 */
	public String generateStr(final int codeLength) {
		final StringBuffer sb = new StringBuffer();
		final Random random = new Random();
		final String sourseStr = charStr;
		for (int i = 0; i < codeLength; i++) {
			sb.append(sourseStr.charAt(random.nextInt(sourseStr.length())));
		}
		return sb.toString();
	}

}